'use strict';

const { Service } = require('ee-core');
const net = require('net');
const ModbusRTU = require("modbus-serial");
const crc16 = require('crc').crc16;
const Electron = require('ee-core/electron');
const { sendMsg, prefixedHex } = require('../common');
/**
 * 示例服务（service层为单例）
 * @class
 */
class NetTCPService extends Service {

  constructor(ctx) {
    super(ctx);

    // 创建 TCP 客户端
    this.client = new net.Socket();
    // 接收响应数据
    this.client.on('data', (data) => {
        console.log('Received data:', data.toString('hex'));
        // 主动向前端发请求
        // channel 前端ipc.on()，监听的路由
        sendMsg(data.toString('hex'), 'receive');
    });
    this.client.on('end', () => {
      console.log('Connection closed');
    })
  }

  async connect(args) {
    const ip = args.ip; // PLC 的 IP 地址
    const port = args.port; // Modbus TCP 端口

    // 连接到 Modbus TCP 服务器
    await this.client.connect(port, ip, () => {
        console.log('Connected to Modbus TCP server');
    });
    return true;
  }

  async send(args) {

      // 从数组创建 Buffer
      // let bufArr = [0x01, 0x01, 0x00, 0x00, 0x00, 0x04];
      let bufStr = args.value;
      const buffer = Buffer.from(bufStr, 'hex');
      console.log('buffer', buffer);

      // 发送请求帧
      return this.client.write(buffer);
  }

  async read(args) {

      // 示例用法：读取从站地址为 1 的设备，从寄存器地址 0 开始读取 2 个寄存器
      const transactionId = 0x0001; // 事务ID通常需要管理其递增
      const functionCode = prefixedHex(args.functionCode);
      const unitId = prefixedHex(args.id); //0x01; // 从站地址
      const startAddress = prefixedHex(args.start);// 0x0000; // 起始寄存器地址
      const quantity = prefixedHex(args.len); //0x0002; // 读取数量
      const requestFrame = await this.buildReadHoldingRegistersRequest(transactionId, functionCode, unitId, startAddress, quantity);
      console.log(requestFrame); // 输出原始的 Buffer
      sendMsg(requestFrame.toString('hex'), 'send');
      return this.client.write(requestFrame);
  }

  /**
 * 构建一个读取保持寄存器的 Modbus TCP 请求帧
 * @param {number} transactionId - 事务标识符（例如：0x0001）
 * @param {number} unitId - 单元标识符（从站地址）
 * @param {number} startAddress - 要读取的起始寄存器地址
 * @param {number} quantity - 要读取的寄存器数量
 * @returns {Buffer} - 包含完整 Modbus TCP 请求帧的 Buffer
 */
async buildReadHoldingRegistersRequest(transactionId, functionCode, unitId, startAddress, quantity) {
  // MBAP 头部固定部分（协议标识符固定为 0x0000）
  const protocolId = 0x0000;
  // 后续字节数：单元标识符 (1) + PDU (功能码 1 + 数据 4 = 5) -> 总长 1+5=6
  const length = 6;
  // 功能码：0x03 代表读取保持寄存器
  // const functionCode = 0x06;

  // 创建一个足够大的 Buffer（MBAP 头 7 字节 + PDU 5 字节 = 12 字节）
  const buffer = Buffer.alloc(12);

  // 写入 MBAP 头（7 字节）
  buffer.writeUInt16BE(transactionId, 0);   // 事务标识符，偏移量 0
  buffer.writeUInt16BE(protocolId, 2);      // 协议标识符，偏移量 2
  buffer.writeUInt16BE(length, 4);          // 长度字段，偏移量 4
  buffer.writeUInt8(unitId, 6);             // 单元标识符，偏移量 6

  // 写入 PDU（5 字节）
  buffer.writeUInt8(functionCode, 7);       // 功能码，偏移量 7
  buffer.writeUInt16BE(startAddress, 8);    // 起始地址，偏移量 8
  buffer.writeUInt16BE(quantity, 10);       // 寄存器数量，偏移量 10

  return buffer;
}

  async close() { 
    // close the connection to the serialport
    // 关闭连接
    this.client.destroy();
  }

  // 轮询读取数据
  async polling(args) { 
    
  }

}

NetTCPService.toString = () => '[class NetTCPService]';
module.exports = NetTCPService;